package main

import (
	"fmt"
	"strings"
)

type Employee struct {
	Name     string
	Age      int
	Vacation int
	Salary   int
}

func main() {
	list := []string{"apple", "banana"}

	x := MapStrToStr(list, func(s string) string {
		return strings.ToUpper(s)
	})

	fmt.Println(x)

	y := MapStrToInt(list, func(s string) int {
		return len(s)
	})

	fmt.Println(y)

	z := Reduce(list, func(s string) int {
		return len(s)
	})

	fmt.Println(z)

	var insert = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	out := Filter(insert, func(n int) bool {
		return n%2 == 1
	})
	fmt.Printf("%v\n", out)

	out = Filter(insert, func(n int) bool {
		return n > 5
	})
	fmt.Printf("%v\n", out)

	var plist = []Employee{
		{"Hao", 44, 0, 8000},
		{"Bob", 34, 10, 5000},
		{"Alice", 23, 5, 9000},
		{"Jack", 26, 0, 4000},
		{"Tom", 48, 9, 7500},
		{"Marry", 29, 0, 6000},
		{"Mike", 32, 8, 4000},
	}

	old := EmployeeCountIf(plist, func(e *Employee) bool {
		return e.Age > 35
	})

	fmt.Println("old people ", old)

	high_pay := EmployeeCountIf(plist, func(e *Employee) bool {
		return e.Salary >= 6000
	})

	fmt.Println("high_pay people ", high_pay)

	no_vacation := EmployeeFilterIn(plist, func(e *Employee) bool {
		return e.Vacation == 0
	})

	fmt.Println("no_vacation people ", no_vacation)

	total_pay := EmployeeSumIf(plist, func(e *Employee) int {
		return e.Salary
	})

	fmt.Printf("Total Salary: %d\n", total_pay)

	younger_pay := EmployeeSumIf(plist, func(e *Employee) int {
		if e.Age < 30 {
			return e.Salary
		}
		return 0
	})

	fmt.Printf("younger_pay Salary: %d\n", younger_pay)

}

func MapStrToStr(arr []string, fn func(s string) string) []string {
	var newArr []string
	for i := 0; i < len(arr); i++ {
		newArr = append(newArr, fn(arr[i]))
	}
	return newArr
}

func MapStrToInt(arr []string, fn func(s string) int) []int {
	var result []int
	for _, s := range arr {
		result = append(result, fn(s))
	}
	return result

}

func Reduce(arr []string, fn func(s string) int) int {
	sum := 0
	for _, it := range arr {
		sum += fn(it)
	}
	return sum
}

func Filter(arr []int, fn func(n int) bool) []int {
	var newArray = []int{}
	for _, it := range arr {
		if fn(it) {
			newArray = append(newArray, it)
		}
	}
	return newArray
}

func EmployeeCountIf(list []Employee, fn func(e *Employee) bool) int {
	count := 0
	for i, _ := range list {
		if fn(&list[i]) {
			count += 1
		}
	}
	return count
}

func EmployeeFilterIn(list []Employee, fn func(e *Employee) bool) []Employee {
	var newList []Employee
	for i, _ := range list {
		if fn(&list[i]) {
			newList = append(newList, list[i])
		}
	}
	return newList
}

func EmployeeSumIf(list []Employee, fn func(e *Employee) int) int {
	var sum = 0
	for i, _ := range list {
		sum += fn(&list[i])
	}
	return sum
}
